package chapter7_取消关闭.volatile取消标志;

import annotation.GuardedBy;
import annotation.ThreadSafe;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

/**
 * 分析：通过在单次循环前，对volatile修饰的取消标志位赋值，来进行任务取消
 * 缺陷：如果单次循环中存在阻塞任务，比如基于生产消费的BlockingQueue的消费者已经停止消费，并调用类似PrimeGenerator.cancel方法停止生产；
 * 因为队列已经满了，且消费者又不会消费，此时生产者的put方法将永远阻塞下去，也不会退出；
 */
@ThreadSafe
public class PrimeGenerator implements Runnable {
    @GuardedBy("this")
    private final List<BigInteger> primes = new ArrayList<>();
    // 变量内存可见性
    private volatile boolean cancelled;

    @Override
    public void run() {
        BigInteger p = BigInteger.ONE;
        while (!cancelled) {
            p = p.nextProbablePrime();
            synchronized (this) {
                primes.add(p);
            }
        }
    }

    public void cancel() {
        cancelled = true;
    }

    public synchronized List<BigInteger> get() {
        //拷贝一个副本，而不是直接把primes发布出去
        return new ArrayList<>(primes);
    }
}
